package httpserver

import (
	"fmt"
	"gitee.com/fierce_wolf/go-fox-edge-common/commEnv"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/FileName"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Map"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"strings"
)

type server struct {
	engine  *gin.Engine
	router  map[string]interface{}
	Respond IRespond
}

func (e *server) RAW(path, method string, handler HandlerRaw, respond IRespond) {
	method = strings.ToUpper(method)
	key := path + ":" + method

	if method == "GET" {
		e.engine.GET(path, func(context *gin.Context) {
			data, err := handler(context)
			respond.Respond(context, data, err)
		})

		Map.SetValue(e.router, key, "mode", "")
		Map.SetValue(e.router, key, "method", handler)
		return
	}
	if method == "DELETE" {
		e.engine.DELETE(path, func(context *gin.Context) {
			data, err := handler(context)
			respond.Respond(context, data, err)
		})

		Map.SetValue(e.router, key, "mode", "")
		Map.SetValue(e.router, key, "method", handler)
		return
	}
	if method == "POST" {
		e.engine.POST(path, func(context *gin.Context) {
			data, err := handler(context)
			respond.Respond(context, data, err)
		})

		Map.SetValue(e.router, key, "mode", "")
		Map.SetValue(e.router, key, "method", handler)
		return
	}
	if method == "PUT" {
		e.engine.PUT(path, func(context *gin.Context) {
			data, err := handler(context)
			respond.Respond(context, data, err)
		})

		Map.SetValue(e.router, key, "mode", "")
		Map.SetValue(e.router, key, "method", handler)
		return
	}
	if method == "PATCH" {
		e.engine.PATCH(path, func(context *gin.Context) {
			data, err := handler(context)
			respond.Respond(context, data, err)
		})

		Map.SetValue(e.router, key, "mode", "")
		Map.SetValue(e.router, key, "handler", handler)
		return
	}
}

func (e *server) GET(path string, handler HandlerGet) {
	e.engine.GET(path, func(context *gin.Context) {
		data, err := handler(context)
		e.Respond.Respond(context, data, err)
	})

	Map.SetValue(e.router, path+":"+"GET", "mode", "")
	Map.SetValue(e.router, path+":"+"GET", "handler", handler)
}

func (e *server) DELETE(path string, handler HandlerDel) {
	e.engine.DELETE(path, func(context *gin.Context) {
		data, err := handler(context)
		e.Respond.Respond(context, data, err)
	})

	Map.SetValue(e.router, path+":"+"DELETE", "mode", "")
	Map.SetValue(e.router, path+":"+"DELETE", "handler", handler)
}

func (e *server) POST(path string, handler HandlerPost) {
	e.engine.POST(path, func(context *gin.Context) {
		body := make(map[string]interface{})
		err := context.ShouldBindJSON(&body)
		if err != nil {
			e.Respond.Respond(context, nil, err)
			return
		}

		data, err := handler(context, body)
		e.Respond.Respond(context, data, err)
	})

	Map.SetValue(e.router, path+":"+"POST", "mode", "")
	Map.SetValue(e.router, path+":"+"POST", "handler", handler)
}

func (e *server) POSTRaw(path string, handler HandlerPost) {
	e.engine.POST(path, func(context *gin.Context) {
		body := make(map[string]interface{})
		err := context.ShouldBindJSON(&body)
		if err != nil {
			e.Respond.Respond(context, nil, err)
			return
		}

		data, err := handler(context, body)
		if err != nil {
			e.Respond.Respond(context, nil, err)
			return
		}
		context.JSON(http.StatusOK, data)
	})

	Map.SetValue(e.router, path+":"+"POST", "mode", "RAW")
	Map.SetValue(e.router, path+":"+"POST", "handler", handler)
}

func (e *server) PUT(path string, handler HandlerPut) {
	e.engine.PUT(path, func(context *gin.Context) {
		body := make(map[string]interface{})
		err := context.ShouldBindJSON(&body)
		if err != nil {
			e.Respond.Respond(context, nil, err)
			return
		}

		data, err := handler(context, body)
		e.Respond.Respond(context, data, err)
	})

	Map.SetValue(e.router, path+":"+"PUT", "mode", "")
	Map.SetValue(e.router, path+":"+"PUT", "handler", handler)
}

func (e *server) startServer(certFile, keyFile string) {
	if certFile == "" || keyFile == "" {
		// 启动HTTP服务
		serverPort := fmt.Sprintf(":%v", commEnv.Service.AppPort)
		fmt.Println("start http server " + serverPort)

		if err := e.engine.Run(serverPort); err != nil {
			log.Fatalf("Failed to start http server: %v", err)
		}
	} else {
		// 使用HTTPS监听443端口
		serverPort := fmt.Sprintf(":%v", commEnv.Service.AppPort)
		fmt.Println("start https server " + serverPort)

		certFile = FileName.GetOsFilePath(commEnv.Service.WorkDir + "/" + certFile)
		keyFile = FileName.GetOsFilePath(commEnv.Service.WorkDir + "/" + keyFile)

		if err := http.ListenAndServeTLS(serverPort, certFile, keyFile, e.engine); err != nil {
			log.Fatalf("Failed to start https server: %v", err)
		}
	}
}
